using System;
using System.Linq;
using Pesta.DataAccess.Azure;
using Pesta.Libraries.OAuth;

namespace raya.Library.OAuth
{
#if AZURE
    public class RayaAzureOAuthDataStore : IOAuthDataStore
    {
        public static readonly RayaAzureOAuthDataStore Instance = new RayaAzureOAuthDataStore();
        private RayaAzureOAuthDataStore()
        {
            
        }

        public OAuthConsumer lookup_consumer(string consumerKey)
        {
            using (var db = new AzureRayaDataContext())
            {
                var result = db.oauthConsumers.Where(k => k.consumer_key == consumerKey).SingleOrDefault();
                if (result == null)
                {
                    return null;
                }
                return new OAuthConsumer(null, result.consumer_key, result.consumer_secret, null); 
            }
        }

        public OAuthToken lookup_token(OAuthConsumer consumer, string tokenType, string token)
        {
            using (var db = new AzureRayaDataContext())
            {
                string consumerKey = consumer.consumerKey;
                string rowkey = string.Concat(token, "_", consumerKey);
                var result = db.oauthTokens
                                .Where(o => o.type == tokenType &&
                                    o.RowKey == rowkey &&
                                    o.PartitionKey == token)
                                .SingleOrDefault();

                if (result == null)
                    throw new OAuthException("Unexpected token type (_token_type) or unknown token");

                return new OAuthToken(result.token_key, result.token_secret); 
            }
        }

        public OAuthToken new_access_token(OAuthToken oauthToken, OAuthConsumer consumer)
        {
            using (var db = new AzureRayaDataContext())
            {
                string partitionKey = oauthToken.key;
                var res = db.oauthTokens
                    .Where(p => p.type == "request" && p.PartitionKey == partitionKey)
                    .SingleOrDefault();
                if (res != null)
                {
                    if (res.authorized != 0)
                    {
                        string tokenKey = Guid.NewGuid().ToString();
                        string tokenSecret = OAuthUtil.md5(DateTime.UtcNow.ToString());
                        var ot = new OAuthTokenRow(tokenKey, string.Concat(tokenKey, "_", tokenSecret))
                        {
                            token_key = tokenKey,
                            type = "access",
                            token_secret = tokenSecret,
                            consumer_key = res.consumer_key,
                            user_id = res.user_id
                        };
                        db.InsertOnSubmit(AzureRayaDataContext.TableNames.oauthTokens, ot);
                        db.DeleteOnSubmit(res);
                        db.SubmitChanges();
                        return new OAuthToken(tokenKey, tokenSecret);
                    }
                } 
            }
            return null;
        }

        public OAuthToken new_request_token(OAuthConsumer consumer)
        {
            using (var db = new AzureRayaDataContext())
            {
                string consumerKey = consumer.consumerKey;
                string consumerSecret = consumer.consumerSecret;
                var result = db.oauthConsumers.Where(p => p.consumer_key == consumerKey && p.consumer_secret == consumerSecret).SingleOrDefault();

                if (result == null)
                    throw new OAuthException("Invalid consumer key (_consumer_key)");

                string tokenKey = Guid.NewGuid().ToString();
                string tokenSecret = OAuthUtil.md5(DateTime.UtcNow.ToString());
                var token = new OAuthTokenRow(tokenKey, string.Concat(tokenKey, "_", tokenSecret))
                {
                    consumer_key = consumerKey,
                    type = "request",
                    token_key = tokenKey,
                    token_secret = tokenSecret,
                    user_id = result.user_id
                };
                db.InsertOnSubmit(AzureRayaDataContext.TableNames.oauthTokens, token);
                db.SubmitChanges();
                return new OAuthToken(tokenKey, tokenSecret); 
            }
        }

        public void authorize_request_token(string token, string userid)
        {
            using (var db = new AzureRayaDataContext())
            {
                var result = db.oauthTokens.Where(t => t.token_key == token).SingleOrDefault();
                if (result != null)
                {
                    result.authorized = 1;
                    result.user_id = userid;
                    db.UpdateOnSubmit(result);
                    db.SubmitChanges();
                } 
            }
        }
    }
#endif
}
